#include "BitmapSocketViaStream.h"
#include "HandleCloseHelper.h"
#include "CommonFunc.h"

#include <windows.h>

#include <stdexcept>

BitmapSocketViaStream::BitmapSocketViaStream()
	:m_IStream(NULL), m_CompressLevel(15)
{
	m_EncoderParameters.Count = 1;
	m_EncoderParameters.Parameter[0].Guid = EncoderQuality;
	m_EncoderParameters.Parameter[0].NumberOfValues = 1;
	m_EncoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
	m_EncoderParameters.Parameter[0].Value = &m_CompressLevel;

	if(GetEncoderClsid(L"image/jpeg", &m_ClsId) != 0)
	{
		throw std::runtime_error("Look for CLSID error");
	}

}

bool BitmapSocketViaStream::SaveBitmapToSocket(Gdiplus::Bitmap &bitmap, int socketFd)
{
// 	const int hSize = 70000;
// 	HGLOBAL hGlobal = GlobalAlloc( GHND, hSize);
// 	if(hGlobal == NULL)
// 	{
// 		throw std::runtime_error("Global alloc error");
// 	}
	
	if(CreateStreamOnHGlobal(NULL, TRUE, &m_IStream) != S_OK)
	{
		throw std::runtime_error("Create stream on hGlobal error");
	}

	bitmap.Save( m_IStream, &m_ClsId, &m_EncoderParameters);

	STATSTG streamStat;
	m_IStream->Stat(&streamStat, STATFLAG_DEFAULT);
	unsigned long bitmapSize = streamStat.cbSize.LowPart;

	HGLOBAL hGlobal;
	if( GetHGlobalFromStream(m_IStream, &hGlobal) != S_OK)
	{
		throw std::runtime_error("Get hGlobal from stream error");
	}
	char *buffer = reinterpret_cast<char*>( GlobalLock(hGlobal) );

	if(!SendData(socketFd, reinterpret_cast<char*>(&bitmapSize), 4))
	{
		throw std::runtime_error("Send bitmap size error");
	}
	if(!SendData(socketFd, buffer, bitmapSize))
	{
		throw std::runtime_error("Send bitmap error");
	}

	m_IStream->Release();

	return true;

}

bool BitmapSocketViaStream::CreateBitmapFromSocket(int socketFd)
{
	unsigned long bitmapSize;
	if(!ReceiveData(socketFd, reinterpret_cast<char*>(&bitmapSize), 4, 4) )
	{
		throw std::runtime_error("Receive bitmap length error");
	}

	HGLOBAL hGlobal = GlobalAlloc(GHND, bitmapSize);
	if(hGlobal == NULL)
	{	
		throw std::runtime_error("Global alloc error");
	}

	char* buffer = reinterpret_cast<char*>( GlobalLock(hGlobal) );
	if(!ReceiveData(socketFd, buffer, bitmapSize, bitmapSize) )
	{
		throw std::runtime_error("Receive bitmap error");
	}

	if (CreateStreamOnHGlobal(hGlobal, TRUE, &m_IStream) != S_OK)
	{
		CloseHandle(hGlobal);
		throw std::runtime_error("Create stream on hGlobal error");
	}

	m_CreatedStream.push_back(m_IStream);

	return true;
}

boost::shared_ptr<Bitmap> BitmapSocketViaStream::getBitmap()
{
	m_IStream = m_CreatedStream.front(); m_CreatedStream.pop_front();
	boost::shared_ptr<Bitmap> bitmap( new Bitmap(m_IStream) );
	m_IStream->Release();
	return bitmap;
}